using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;

namespace DimensionsHelper.LanguageService.Syntax;

public class RangeExpression : Expression
{
    
    public static RangeExpression Empty => new(SyntaxToken.Default, null);

    public static bool IsEmptyRange([NotNullWhen(false)] RangeExpression? expression)
    {
        return expression == null || ReferenceEquals(expression, Empty) ||
               (IsEmptyExpression(expression.LeftBoundary) && IsEmptyExpression(expression.RightBoundary));
    }
    
    
    internal RangeExpression(SyntaxToken toKeywordToken, SyntaxNode? parent) : 
        base(SyntaxKinds.RangeExpression, parent)
    {
        ToKeywordToken = toKeywordToken;
        ToKeywordToken.Parent = this;
    }

    private Expression _left = EmptyExpression.Default;
    private Expression _right = EmptyExpression.Default;


    public Expression LeftBoundary => _left;
    
    public Expression RightBoundary => _right;

    public SyntaxToken ToKeywordToken { get; }


    public void Update(Expression leftBoundary, Expression rightBoundary)
    {
        SetChildField(ref _left, IsEmptyExpression, leftBoundary);
        SetChildField(ref _right, IsEmptyExpression, rightBoundary);
    }

    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        Accept(visitor, LeftBoundary, ToKeywordToken, RightBoundary);
    }
}

public static partial class NodeFactory
{
    /// <summary>
    ///     创建一个区间表达式，语法格式是：LeftBound To RightBound，
    ///     此区间是闭区间
    /// </summary>
    /// <param name="left">左区间</param>
    /// <param name="toKeywordToken">To关键字</param>
    /// <param name="right">右区间</param>
    /// <param name="parent">父节点</param>
    public static RangeExpression CreateRangeExpression(Expression left, SyntaxToken toKeywordToken, Expression right,
        SyntaxNode? parent)
    {
        Debug.Assert(toKeywordToken.IsNode(SyntaxKinds.ToKeywordToken));
        RangeExpression rangeExpression = new(toKeywordToken, parent);
        rangeExpression.Update(left, right);
        return rangeExpression;
    }
}
